module event_trigger;
    
    event e1, e2, e3;

    // P1: Triggers the event using "->" operator
    initial begin
        #10 -> e1;
        $display ("@[%0t] P1: triggered e1", $time);
        #10 -> e2;
        $display ("@[%0t] P1: triggered e2", $time);
        #10 -> e3;
        $display ("@[%0t] P1: triggered e3", $time);
        #100; $finish;
    end

    // P2: Waits for the event using "@" operator
    initial begin
        // P1 中的 ->e1 和 P2 中的 @e1 都在时间 #10 发生
        // SystemVerilog 调度器对于在同一时间片内处于 Active 区域的多个进程, 其执行顺序是不确定的
        // 有可能 P1 的 ->e1 在调度上略微优先于 P2 的 @e1
        // 因此当 P2 执行 @e1 时, e1 事件已经被触发过了.
        // @e1 错过了这个刚刚发生的触发，所以 P2 继续阻塞，等待下一次 e1 的触发.
        // 类似于边沿触发的信号
        #10 @e1;
        $display ("@[%0t] P2: received e1 trigger using @", $time);
    end

    // P3: Waits for the event using ".triggered"
    initial begin
        // e1.triggered 会在事件被触发后的当前时间槽内保持 true，直到当前时间槽结束.
        // 类似于电平触发的信号
        #10 wait(e1.triggered);
        $display ("@[%0t] P3: received e1 trigger using wait", $time);
    end
    
    // P4: Waits for the event using "@" operator
    initial begin
        #10 @e2;
        $display ("@[%0t] P4: received e2 trigger using wait", $time);
    end
    
    // P5: Waits for the event using ".triggered"
    initial begin
        #10 wait(e2.triggered);
        $display ("@[%0t] P5: received e2 trigger using wait", $time);
    end

    // P6: Waits for the event using ".triggered"
    initial begin
        // 命名事件 e3 的 triggered 属性在其被触发的当前时间槽内为真, 并且会持续整个当前时间槽.
        // 之前的时间触发事件 e3, 但在之后的仿真时间事件 e3 没有被触发, 则 e3.triggered 在之后的仿真时间为 false.
        #40 wait(e3.triggered);
        $display ("@[%0t] P6: received e3 trigger using wait", $time);
    end

endmodule
